package com.baoji.auth.config;

import com.baoji.auth.filter.JWTAuthenticationEntryPoint;
import com.baoji.auth.filter.JWTAuthenticationFilter;
import com.baoji.auth.filter.JWTAuthorizationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

/**
 * @Auther: ghm
 * @Date: 2021/09/24/17:19
 * @Description: SpringSecurity 配置类
 */
@EnableWebSecurity//配置Web安全过滤器和启用全局认证机制
@EnableGlobalMethodSecurity(prePostEnabled = true)// 启用方法级别的权限认证
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    @Qualifier("userDetailsServiceImpl")
    private UserDetailsService userDetailsService;

    // 密码加密对象：采用SHA-256 +随机盐+密钥对密码进行加密
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // userDetailsService：查询数据库用户信息进行登录校验，
        // bCryptPasswordEncoder()：加入密码编码器，对加密密码校验
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 跨域共享（允许跨域）
        http.cors()
                .and()
                // 跨域伪造请求限制无效
                .csrf().disable()
                .authorizeRequests()
                // 需要登录验证了的用户才能访问
                //.antMatchers("/admin/**")
                //.authenticated()
                // 访问 /data 资源需要 ADMIN 角色
                .antMatchers("/data").hasRole("ADMIN")
                // 其余资源任何人都可以访问
                .anyRequest().permitAll()
//                .and()
//                .logout()
//                .logoutUrl("/logout")
//                // 退出登录之后重定向到登录页
//                .logoutSuccessUrl("/login")
                .and()
                // 添加 JWT登录拦截器
                .addFilter(new JWTAuthenticationFilter(authenticationManager()))
                // 添加 JWT权限拦截器
                .addFilter(new JWTAuthorizationFilter(authenticationManager()))
                .sessionManagement()
                // 设置 Session 的创建策略为：Spring Security 永不创建 HttpSession 不使用 HttpSession 来获取 SecurityContext
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                // 异常处理
                .exceptionHandling()
                // 匿名用户无访问权限资源时的异常
                .authenticationEntryPoint(new JWTAuthenticationEntryPoint());
    }


    @Bean
    CorsConfigurationSource corsConfigurationSource() {

        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        // 注册跨域配置
        source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
        return source;
    }
}
